﻿/* *
 * =============================================================================
 * File Name:               Page.xaml.cs
 * Project:                 Sierpinski's Triangle
 * Programmer:              Ken Watts
 * Creation Date:           8/3/2008
 * =============================================================================
 * Description:             Program that renders Sierpinski's triangle in 
 *                          Silverlight.
 * =============================================================================
 * Modification Date:       8/3/2008 - Initial Revision
 * =============================================================================
 * */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Silverlight.Samples;

namespace SierpinskiTriangle
{
    public partial class Page : UserControl
    {
        // Constants
        const int k_int_timer_interval_ms = 100;
        const int k_int_max_width = 300;
        const int k_int_max_height = 300;
        const int k_int_points_per_tick = 100;
        const double k_dbl_pt1_x = k_int_max_width/2.0;
        const double k_dbl_pt1_y = 0.0;
        const double k_dbl_pt2_x = 0.0;
        const double k_dbl_pt2_y = (double)k_int_max_height - 1;
        const double k_dbl_pt3_x = (double)k_int_max_width-1;
        const double k_dbl_pt3_y = (double)k_int_max_height - 1;
        // Global class variables
        Point pt, pt1, pt2, pt3;
        EditableImage _ei = null;
        BitmapImage image;
        Random rand;

        public Page()
        {
            InitializeComponent();
            this.MouseLeftButtonDown += new MouseButtonEventHandler(CustomMouseLeftButtonDown);
        }

        // Get the midpoint
        Point MidPoint(Point pt1, Point pt2)
        {
            pt.X = (pt1.X + pt2.X) / 2;
            pt.Y = (pt1.Y + pt2.Y) / 2;
            return pt;
        }

        void Page_Loaded(object o, EventArgs args)
        {
            image = new BitmapImage();
            // Set timer 
            DispatcherTimer dt = new DispatcherTimer();
            dt.Interval = new TimeSpan(0, 0, 0, 0, k_int_timer_interval_ms);
            dt.Tick += new EventHandler(dt_Tick);
            // Start the timer
            dt.Start();
        }

        void dt_Tick(object sender, EventArgs e)
        {
            // Re-use a single EditableImage
            if (null == _ei)
            {
                _ei = new EditableImage(k_int_max_height, k_int_max_width);
                // Clear the image
                for (int idx = 0; idx < k_int_max_height; idx++)    
                {
                    for (int jdx = 0; jdx < k_int_max_width; jdx++) 
                    {
                        _ei.SetPixel(jdx, idx, 0xFF, 0xFF, 0xFF, 0xFF);
                    }
                }
                pt1 = new Point(k_dbl_pt1_x, k_dbl_pt1_y);
                pt2 = new Point(k_dbl_pt2_x, k_dbl_pt2_y);
                pt3 = new Point(k_dbl_pt3_x, k_dbl_pt3_y);
                // Pick a random starting point
                rand = new Random(DateTime.Now.Millisecond);
                pt = new Point(rand.NextDouble() * (k_int_max_width - 1), rand.NextDouble() * (k_int_max_height - 1));
            }

            for (int cnt = 0; cnt < k_int_points_per_tick; cnt++)
            {
                // Plot a new point
                switch (rand.Next(3))
                {
                    case 0:
                        pt=MidPoint(pt, pt1);
                        _ei.SetPixel((int)pt.X, (int)pt.Y, 0xFF, 0x00, 0x00, 0xFF);
                        break;
                    case 1:
                        pt = MidPoint(pt, pt2);
                        _ei.SetPixel((int)pt.X, (int)pt.Y, 0x00, 0xFF, 0x00, 0xFF);
                        break;
                    case 2:
                        pt = MidPoint(pt, pt3);
                        _ei.SetPixel((int)pt.X, (int)pt.Y, 0x00, 0x00, 0xFF, 0xFF);
                        break;
                    default:
                        break;
                }
            }
            // Get stream and set image source
            image.SetSource(_ei.GetStream());
            img.Source = image;
        }

        protected virtual void CustomMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // Clear the image
            for (int idx = 0; idx < k_int_max_height; idx++)  
            {
                for (int jdx = 0; jdx < k_int_max_width; jdx++)
                {
                    _ei.SetPixel(jdx, idx, 0xFF, 0xFF, 0xFF, 0xFF); // White background
                }
            }
        }
    }
}
